﻿#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    tcpServer = new QTcpServer(this);
    if(!tcpServer->listen(QHostAddress::LocalHost,6666)) //本地主机的6666端口，如果出错就输出错误信息，并关闭
    {
        qDebug() << tcpServer->errorString();
        close();
    }
    connect(tcpServer,SIGNAL(newConnection()),this,SLOT(sendMessage()));//连接信号和相应槽函数
}

Widget::~Widget()
{
    delete ui;
}

/*******************************************************************************************
    这个是数据发送函数
    （1）为了保证在客户端能接收到完整的文件，我们都在数据流的最开始写入完整文件的大小信息，
    这样客户端就可以根据大小信息来判断是否接受到了完整的文件。
    而在服务器端，在发送数据时就要首先发送实际文件的大小信息，
    但是，文件的大小一开始是无法预知的，所以这里先使用了out<<(quint16) 0;
    在block的开始添加了一个quint16大小的空间，也就是两字节的空间，它用于后面放置文件的大小信息。
    然后out<<tr("hello Tcp!!!");输入实际的文件，这里是字符串。
    当文件输入完成后我们再使用out.device()->seek(0);
    返回到block的开始，加入实际的文件大小信息，也就是后面的代码，
    它是实际文件的大小：out<<(quint16) (block.size() - sizeof(quint16));

    （2）在服务器端我们可以使用tcpServer的nextPendingConnection()函数来获取已经建立的连接的Tcp套接字，
    使用它来完成数据的发送和其它操作。这里，我们关联了disconnected()信号和deleteLater()槽，然后我们发送数据

    数据流版本：QDataStream::Qt_4_6
****************************************************************************************************/
void Widget::sendMessage()
{    
    QByteArray block;//用于暂存我们要发送的数据
    QDataStream out(&block,QIODevice::WriteOnly);//使用数据流写入数据

    out.setVersion(QDataStream::Qt_4_6);//设置数据流的版本，客户端和服务器端使用的版本要相同
    out<<(quint16) 0;
    out<<tr("hello Tcp!!!");
    out.device()->seek(0);
    out<<(quint16) (block.size() - sizeof(quint16));

    QTcpSocket *clientConnection = tcpServer->nextPendingConnection();//我们获取已经建立的连接的子套接字

    connect(clientConnection,SIGNAL(disconnected()),clientConnection,SLOT(deleteLater()));
    clientConnection->write(block);
    clientConnection->disconnectFromHost();

    ui->statusLabel->setText("send message successful!!!");//发送数据成功后，显示提示
}
